òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/11251

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

# 뺯
import jqdata
import numpy as np
import pandas as pd
import bisect
# ʼ趨׼ȵ
def initialize(context):
    #׼ָ
    g.benchmark_index = '000300.XSHG'
    # ҪĹƱg.Ϊȫֱ
    g.buy_index = '160706.XSHE'
    set_benchmark(g.benchmark_index)
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)
    # ˵orderϵAPIıerror͵log
    log.set_level('order', 'error')
    set_commission(PerTrade(buy_cost=0.0015, sell_cost=0.005))

    # 
    run_monthly(fnud_main, 1, time='open')
    run_monthly(fnud_close, 1, time='after_close')
    run_daily(fund_sell, time='every_bar')
    g.Totalmonth = 0
    g.TotalCash = 0
    g.MaxCash = 0
    g.LastCash = 1000   #ÿ¶Ͷ
    g.pe_now=0
    # ݵ־ log.info()
    log.info("Ͷָ%sͶ%s,ÿ¶Ͷȣ%s" %(get_security_info(g.benchmark_index).display_name , get_security_info(g.buy_index).display_name,g.LastCash))
    log.info("------------------------------------------------------")
    send_message("Ͷָ%sͶ%s,ÿ¶Ͷȣ%s" %(get_security_info(g.benchmark_index).display_name , get_security_info(g.buy_index).display_name,g.LastCash))
    
def fnud_main(context):
    g.Totalmonth += 1
    df = get_index_pes(context)
    g.pe_now = float(df.ix[0,2]) / 100 #ǰPEٷֱ log.info(df)
    if g.pe_now <0.4:
        g.pe_ratio = 1.5;
    elif g.pe_now < 0.6:
        g.pe_ratio = 1.0;
    elif g.pe_now < 0.8:
        g.pe_ratio = 0.5;
    else:
        g.pe_ratio = -999;
    cash = g.pe_ratio * g.LastCash
    g.LastCash = g.LastCash * 1.01
    order_value(g.buy_index, cash)    #Ͷ5000
    # ΢ŷϢģ⽻ף΢Ч
    send_message("Month %d 300ǰPEٷֱ: %.2f (%s)%.2f" %(g.Totalmonth,g.pe_now,g.buy_index, cash))
    log.info("Month %d   ǰPEٷֱ: %.2f  " %(g.Totalmonth,g.pe_now))
    
def fund_sell(context):
    if (g.pe_now > 0.75 ) & (context.portfolio.positions_value >0):
        df = get_index_pes(context)
        g.pe_now = float(df.ix[0,2]) / 100 #ǰPEٷֱ log.info(df)
        if g.pe_now >= 0.8:
            order_target_value(g.buy_index, 0)  #ȫ
            log.info("ȫ")
            send_message("ȫ")
    
def fnud_close(context):
    #õж
    orders = get_orders()
    cash = 0.0
    for _order in orders.values():
        cash = float(_order.price) * float(_order.filled)
        if _order.is_buy == False:
            cash = cash * -1.0;
        g.TotalCash += cash
        if g.MaxCash < g.TotalCash:
            g.MaxCash = g.TotalCash
        if g.TotalCash <= 0:
            g.TotalCash = 0
    # ȡ˻ĳֲֵּ
    positions_value = context.portfolio.positions_value
    available_cash = context.portfolio.available_cash
    returns = context.portfolio.returns * 100
    log.info("Ͷ: %dͶ: %d: %s" %(g.TotalCash , g.MaxCash,cash))
    log.info("ǰֲ: %.2f˻%.2fȨۼʣ%.2f" %(positions_value , available_cash , returns))
    log.info("------------------------------------------------------")

def on_strategy_end(context):
    log.info("زͶ: %dͶ: %d" %(g.TotalCash , g.MaxCash))
    # ȡ˻ĳֲֵּ
    positions_value = context.portfolio.positions_value
    available_cash = context.portfolio.available_cash
    returns = context.portfolio.returns * 100
    log.info("ǰֲ: %.2f˻%.2fȨۼʣ%.2f" %(positions_value , available_cash , returns))

################################### Զ庯 ###############################
#ָڵָPEȨأ
def get_index_pe_date(index_code,date):
    stocks = get_index_stocks(index_code, date)
    q = query(valuation).filter(valuation.code.in_(stocks))
    df = get_fundamentals(q, date)
    if len(df)>0:
        pe = len(df)/sum([1/p if p>0 else 0 for p in df.pe_ratio])
        return pe
    else:
        return float('NaN')
    
#ָʷPE
def get_index_pe(index_code,today):
    start= get_security_info(index_code).start_date 
    #end = pd.datetime.today();
    end = today;
    dates=[]
    pes=[]
    for d in pd.date_range(start,end,freq='M'): #ƵΪ
    #for d in jqdata.get_trade_days(start_date=start, end_date=end): #ƵΪ죬
        dates.append(d)
        pes.append(get_index_pe_date(index_code,d))
    return pd.Series(pes, index=dates)
#ȡָPE
def get_index_pes(context):
    today = context.current_dt
    all_index = get_all_securities(['index'])
    index_choose =[g.benchmark_index]
    df_pe = pd.DataFrame()
    for code in index_choose:
        #print(u'ڴ: ',code) 
        df_pe[code]=get_index_pe(code,today)

    #today= pd.datetime.today()
    results=[]
    for code in index_choose:
        pe = get_index_pe_date(code,today)
        q_pes = [df_pe.quantile(i/10.0)[code]  for i in range(11)]
        idx = bisect.bisect(q_pes,pe)
        quantile = idx-(q_pes[idx]-pe)/(q_pes[idx]-q_pes[idx-1])
        index_name = all_index.ix[code].display_name
        results.append([index_name,'%.2f'% pe,'%.2f'% (quantile*10)]+['%.2f'%q  for q in q_pes]+[df_pe[code].count()])
    columns=[u'',u'ǰPE',u'λ%',u'СPE']+['%d%%'% (i*10) for i in range(1,10)]+[u'PE' , u"ݸ"]
    return pd.DataFrame(data=results,index=index_choose,columns=columns)



